export default class WebsocketUtil {
  /** 是否连接成功 */
  isOpenSocket: boolean
  /** 地址 */
  url: string
  /** 心跳检测 */
  data: any
  /** 多少秒执行检测 */
  timeout: number
  /** 检测服务器端是否还活着 */
  heartbeatInterval: NodeJS.Timeout | null
  /** 重连之后多久再次重连 */
  reconnectTimeout: NodeJS.Timeout | null
  /** 监听 */
  socketTask: UniApp.SocketTask|null
  constructor(url: string, time: number = 5000) {
    this.isOpenSocket = false
    this.url = url
    this.data = null
    this.timeout = time
    this.heartbeatInterval = null
    this.reconnectTimeout = null
    this.socketTask = null

    try {
      // 创建连接
      this.connectSocketInit()
    } catch (error) {
      // 连接失败
      console.log('连接失败')
      this.isOpenSocket = false
      this.reconnect()
    }
  }

  connectSocketInit() {
    this.socketTask = uni.connectSocket({
      url: this.url,
      success: (res) => {
        console.log('正在链接中...');
        return this.socketTask
      }
    })
    this.socketTask.onOpen(() => {
      console.log('链接成功');
      this.reconnectTimeout && clearTimeout(this.reconnectTimeout)
      this.heartbeatInterval && clearInterval(this.heartbeatInterval)
      // 连接成功
      this.isOpenSocket = true
      this.start()
    })
  }

  send(value:{[key:string]:any}) {
    return new Promise((resolve, reject) => {
      this.socketTask?.send({
        data: JSON.stringify(value),
        success: (res) => {
          console.log('发送成功');
          resolve(res)
        },
        fail: (err) => {
          console.log('发送失败');
          reject(err)
        }
      })
    })
  }

  start() {
    this.heartbeatInterval = setInterval(() => {
      this.data = { value: '心跳检测', method: 'heartbeat'}
      this.send(this.data)
    }, this.timeout)
  }

  reconnect() {
    this.heartbeatInterval && clearInterval(this.heartbeatInterval)
    if(!this.isOpenSocket) {
      this.reconnectTimeout = setTimeout(() => {
        this.connectSocketInit()
      }, 3000)
    }

  }

  getMessage(callback: (data:any) => void) {
    this.socketTask?.onMessage((res) => {
      callback(res.data)
    })
  }
}